Rename GtkPopoverBar to GtkPopoverMenuBar
authorMatthias Clasen <mclasen@redhat.com>
Sun, 9 Jun 2019 16:19:07 +0000 (16:19 +0000)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 9 Jun 2019 17:42:07 +0000 (17:42 +0000)
Clarity over beauty.

demos/widget-factory/widget-factory.ui
gtk/gtk.h
gtk/gtkpopoverbar.c [deleted file]
gtk/gtkpopoverbar.h [deleted file]
gtk/gtkpopovermenubar.c [new file with mode: 0644]
gtk/gtkpopovermenubar.h [new file with mode: 0644]
gtk/meson.build

index 7b873fbc8a297adddeef2f9b4e0a7b2d52cb58ca..f4292d5a1e71762941d89b5467f90f0b86436999 100644 (file)
@@ -1822,7 +1822,7 @@ microphone-sensitivity-medium-symbolic</property>
                                   <object class="GtkBox">
                                     <property name="orientation">vertical</property>
                                     <child>
-                                      <object class="GtkPopoverBar">
+                                      <object class="GtkPopoverMenuBar">
                                         <property name="menu-model">menu_bar_model</property>
                                       </object>
                                     </child>
index 9bb5145c3d1e86f42e482af04ed50501eff4a38d..6691d286c9bc0006798534eb12e5c166415ca9f3 100644 (file)
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
 #include <gtk/gtkpasswordentry.h>
 #include <gtk/gtkpicture.h>
 #include <gtk/gtkpopover.h>
-#include <gtk/gtkpopoverbar.h>
 #include <gtk/gtkpopovermenu.h>
+#include <gtk/gtkpopovermenubar.h>
 #include <gtk/gtkprintcontext.h>
 #include <gtk/gtkprintoperation.h>
 #include <gtk/gtkprintoperationpreview.h>
diff --git a/gtk/gtkpopoverbar.c b/gtk/gtkpopoverbar.c
deleted file mode 100644 (file)
index 49c1337..0000000
+++ /dev/null
@@ -1,539 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2019 Red Hat, Inc.
- *
- * Authors:
- * - Matthias Clasen <mclasen@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-
-#include "gtkpopoverbar.h"
-#include "gtkpopovermenu.h"
-
-#include "gtkboxlayout.h"
-#include "gtklabel.h"
-#include "gtkmenubutton.h"
-#include "gtkintl.h"
-#include "gtkprivate.h"
-#include "gtkmarshalers.h"
-#include "gtkstylecontext.h"
-#include "gtkgestureclick.h"
-#include "gtkeventcontrollerkey.h"
-#include "gtkeventcontrollermotion.h"
-#include "gtkactionmuxerprivate.h"
-#include "gtkmenutracker.h"
-#include "gtkwidgetprivate.h"
-#include "gtkmain.h"
-#include "gtknative.h"
-
-#define GTK_TYPE_POPOVER_BAR_ITEM    (gtk_popover_bar_item_get_type ())
-#define GTK_POPOVER_BAR_ITEM(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_BAR_ITEM, GtkPopoverBarItem))
-#define GTK_IS_POPOVER_BAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_BAR_ITEM))
-
-GType gtk_popover_bar_item_get_type (void) G_GNUC_CONST;
-
-typedef struct _GtkPopoverBarItem GtkPopoverBarItem;
-
-struct _GtkPopoverBar
-{
-  GtkWidget parent;
-
-  GMenuModel *model;
-  GtkMenuTracker *tracker;
-
-  GtkPopoverBarItem *active_item;
-};
-
-typedef struct _GtkPopoverBarClass GtkPopoverBarClass;
-struct _GtkPopoverBarClass
-{
-  GtkWidgetClass parent_class;
-};
-
-struct _GtkPopoverBarItem
-{
-  GtkWidget parent;
-
-  GtkWidget *label;
-  GtkPopover *popover;
-};
-
-typedef struct _GtkPopoverBarItemClass GtkPopoverBarItemClass;
-struct _GtkPopoverBarItemClass
-{
-  GtkWidgetClass parent_class;
-
-  void (* activate) (GtkPopoverBarItem *item);
-};
-
-G_DEFINE_TYPE (GtkPopoverBarItem, gtk_popover_bar_item, GTK_TYPE_WIDGET)
-
-static void
-set_active_item (GtkPopoverBar     *bar,
-                 GtkPopoverBarItem *item,
-                 gboolean           popup)
-{
-  gboolean changed;
-  gboolean was_popup;
-
-  changed = item != bar->active_item;
-
-  if (bar->active_item)
-    was_popup = gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover));
-  else
-    was_popup = FALSE;
-
-  if (was_popup && changed)
-    gtk_popover_popdown (bar->active_item->popover);
-
-  if (changed)
-    {
-      GtkStyleContext *context;
-
-      if (bar->active_item)
-        {
-          context = gtk_widget_get_style_context (GTK_WIDGET (bar->active_item));
-          gtk_style_context_remove_class (context, "active");
-        }
-
-      bar->active_item = item;
-
-      if (bar->active_item)
-        {
-          context = gtk_widget_get_style_context (GTK_WIDGET (bar->active_item));
-          gtk_style_context_add_class (context, "active");
-        }
-    }
-
-  if (bar->active_item)
-    {
-      if (popup || (was_popup && changed))
-        gtk_popover_popup (bar->active_item->popover);
-      else if (changed)
-        gtk_widget_grab_focus (GTK_WIDGET (bar->active_item));
-    }
-}
-
-static void
-clicked_cb (GtkGesture *gesture,
-            int         n,
-            double      x,
-            double      y,
-            gpointer    data)
-{
-  GtkWidget *target;
-  GtkPopoverBar *bar;
-
-  target = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
-  bar = GTK_POPOVER_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_BAR));
-
-  set_active_item (bar, GTK_POPOVER_BAR_ITEM (target), TRUE);
-}
-
-static void
-enter_cb (GtkEventController *controller,
-          double              x,
-          double              y,
-          GdkCrossingMode     mode,
-          GdkNotifyType       type,
-          gpointer            data)
-{
-  GtkWidget *target;
-  GtkPopoverBar *bar;
-
-  target = gtk_event_controller_get_widget (controller);
-
-  bar = GTK_POPOVER_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_BAR));
-
-  set_active_item (bar, GTK_POPOVER_BAR_ITEM (target), FALSE);
-}
-
-static gboolean
-gtk_popover_bar_focus (GtkWidget        *widget,
-                       GtkDirectionType  direction)
-{
-  GtkPopoverBar *bar = GTK_POPOVER_BAR (widget);
-  GtkWidget *next;
-  if (bar->active_item &&
-      gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover)))
-    {
-      if (gtk_widget_child_focus (GTK_WIDGET (bar->active_item->popover), direction))
-        return TRUE;
-    }
-
-  if (direction == GTK_DIR_LEFT)
-    {
-      if (bar->active_item)
-        next = gtk_widget_get_prev_sibling (GTK_WIDGET (bar->active_item));
-      else
-        next = NULL;
-
-      if (next == NULL)
-        next = gtk_widget_get_last_child (GTK_WIDGET (bar));
-    }
-  else if (direction == GTK_DIR_RIGHT)
-    {
-      if (bar->active_item)
-        next = gtk_widget_get_next_sibling (GTK_WIDGET (bar->active_item));
-      else
-        next = NULL;
-
-      if (next == NULL)
-        next = gtk_widget_get_first_child (GTK_WIDGET (bar));
-    }
-  else
-    return FALSE;
-
-  set_active_item (bar, GTK_POPOVER_BAR_ITEM (next), FALSE);
-
-  return TRUE;
-}
-
-static void
-gtk_popover_bar_item_init (GtkPopoverBarItem *item)
-{
-  GtkEventController *controller;
-
-  gtk_widget_set_can_focus (GTK_WIDGET (item), TRUE);
-
-  item->label = g_object_new (GTK_TYPE_LABEL,
-                              "use-underline", TRUE,
-                              NULL);
-  gtk_widget_set_parent (item->label, GTK_WIDGET (item));
-
-  controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
-  g_signal_connect (controller, "pressed", G_CALLBACK (clicked_cb), NULL);
-  gtk_widget_add_controller (GTK_WIDGET (item), controller);
-
-  controller = gtk_event_controller_motion_new ();
-  gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
-  g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), NULL);
-  gtk_widget_add_controller (GTK_WIDGET (item), controller);
-}
-
-static void
-gtk_popover_bar_item_dispose (GObject *object)
-{
-  GtkPopoverBarItem *item = GTK_POPOVER_BAR_ITEM (object);
-
-  g_clear_pointer (&item->label, gtk_widget_unparent);
-  g_clear_pointer ((GtkWidget **)&item->popover, gtk_widget_unparent);
-
-  G_OBJECT_CLASS (gtk_popover_bar_item_parent_class)->dispose (object);
-}
-
-static void
-gtk_popover_bar_item_finalize (GObject *object)
-{
-  G_OBJECT_CLASS (gtk_popover_bar_item_parent_class)->finalize (object);
-}
-
-static void
-gtk_popover_bar_item_measure (GtkWidget      *widget,
-                              GtkOrientation  orientation,
-                              int             for_size,
-                              int            *minimum,
-                              int            *natural,
-                              int            *minimum_baseline,
-                              int            *natural_baseline)
-{
-  GtkPopoverBarItem *item = GTK_POPOVER_BAR_ITEM (widget);
-
-  gtk_widget_measure (item->label, orientation, for_size,
-                      minimum, natural,
-                      minimum_baseline, natural_baseline);
-}
-
-static void
-gtk_popover_bar_item_size_allocate (GtkWidget *widget,
-                                    int        width,
-                                    int        height,
-                                    int        baseline)
-{
-  GtkPopoverBarItem *item = GTK_POPOVER_BAR_ITEM (widget);
-
-  gtk_widget_size_allocate (item->label,
-                            &(GtkAllocation) { 0, 0, width, height },
-                            baseline);
-
-  gtk_native_check_resize (GTK_NATIVE (item->popover));
-}
-
-static void
-gtk_popover_bar_item_activate (GtkPopoverBarItem *item)
-{
-  gtk_popover_popup (GTK_POPOVER (item->popover));
-}
-
-static void
-gtk_popover_bar_item_class_init (GtkPopoverBarItemClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
-  object_class->dispose = gtk_popover_bar_item_dispose;
-  object_class->finalize = gtk_popover_bar_item_finalize;
-
-  widget_class->measure = gtk_popover_bar_item_measure;
-  widget_class->size_allocate = gtk_popover_bar_item_size_allocate;
-
-  klass->activate = gtk_popover_bar_item_activate;
-
-  widget_class->activate_signal =
-    g_signal_new (I_("activate"),
-                  G_OBJECT_CLASS_TYPE (object_class),
-                  G_SIGNAL_RUN_FIRST,
-                  G_STRUCT_OFFSET (GtkPopoverBarItemClass, activate),
-                  NULL, NULL,
-                  NULL,
-                  G_TYPE_NONE, 0);
-
-  gtk_widget_class_set_css_name (widget_class, I_("item"));
-}
-enum
-{
-  PROP_0,
-  PROP_MENU_MODEL,
-  LAST_PROP
-};
-
-static GParamSpec * bar_props[LAST_PROP];
-
-G_DEFINE_TYPE (GtkPopoverBar, gtk_popover_bar, GTK_TYPE_WIDGET)
-
-static void
-tracker_remove (gint     position,
-                gpointer user_data)
-{
-  GtkWidget *bar = user_data;
-  GtkWidget *child;
-  int i;
-
-  for (child = gtk_widget_get_first_child (bar), i = 0;
-       child;
-       child = gtk_widget_get_next_sibling (child), i++)
-    {
-      if (i == position)
-        {
-          gtk_widget_destroy (child);
-          break;
-        }
-    }
-}
-
-static void
-popover_unmap (GtkPopover    *popover,
-               GtkPopoverBar *bar)
-{
-  if (bar->active_item && bar->active_item->popover == popover)
-    set_active_item (bar, NULL, FALSE);
-}
-
-static void
-tracker_insert (GtkMenuTrackerItem *item,
-                gint                position,
-                gpointer            user_data)
-{
-  GtkPopoverBar *bar = user_data;
-
-  if (gtk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU))
-    {
-      GtkPopoverBarItem *widget;
-      GMenuModel *model;
-      GtkWidget *sibling;
-      GtkWidget *child;
-      GtkPopover *popover;
-      int i;
-
-      widget = g_object_new (GTK_TYPE_POPOVER_BAR_ITEM, NULL);
-      g_object_bind_property (item, "label",
-                              widget->label, "label",
-                              G_BINDING_SYNC_CREATE);
-
-      model = _gtk_menu_tracker_item_get_link (item, G_MENU_LINK_SUBMENU);
-      popover = GTK_POPOVER (gtk_popover_menu_new_from_model (GTK_WIDGET (widget), model));
-      gtk_popover_set_position (popover, GTK_POS_BOTTOM);
-      gtk_popover_set_has_arrow (popover, FALSE);
-      gtk_widget_set_halign (GTK_WIDGET (popover), GTK_ALIGN_START);
-
-      g_signal_connect (popover, "unmap", G_CALLBACK (popover_unmap), bar);
-
-      widget->popover = popover;
-
-      sibling = NULL;
-      for (child = gtk_widget_get_first_child (GTK_WIDGET (bar)), i = 1;
-           child;
-           child = gtk_widget_get_next_sibling (child), i++)
-        {
-          if (i == position)
-            {
-              sibling = child;
-              break;
-            }
-        }
-      gtk_widget_insert_after (GTK_WIDGET (widget), GTK_WIDGET (bar), sibling);
-    }
-  else
-    g_warning ("Don't know how to handle this item");
-}
-
-static void
-gtk_popover_bar_set_property (GObject      *object,
-                              guint         property_id,
-                              const GValue *value,
-                              GParamSpec   *pspec)
-{
-  GtkPopoverBar *bar = GTK_POPOVER_BAR (object);
-
-  switch (property_id)
-    {
-      case PROP_MENU_MODEL:
-        gtk_popover_bar_set_menu_model (bar, g_value_get_object (value));
-        break;
-
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-}
-
-static void
-gtk_popover_bar_get_property (GObject    *object,
-                              guint       property_id,
-                              GValue     *value,
-                              GParamSpec *pspec)
-{
-  GtkPopoverBar *bar = GTK_POPOVER_BAR (object);
-
-  switch (property_id)
-    {
-      case PROP_MENU_MODEL:
-        g_value_set_object (value, bar->model);
-        break;
-
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
-    }
-}
-
-
-static void
-gtk_popover_bar_dispose (GObject *object)
-{
-  GtkPopoverBar *bar = GTK_POPOVER_BAR (object);
-  GtkWidget *child;
-
-  g_clear_pointer (&bar->tracker, gtk_menu_tracker_free);
-  g_clear_object (&bar->model);
-
-  while ((child = gtk_widget_get_first_child (GTK_WIDGET (bar))))
-    gtk_widget_destroy (child);
-
-  G_OBJECT_CLASS (gtk_popover_menu_bar_parent_class)->dispose (object);
-}
-
-static void
-gtk_popover_bar_class_init (GtkPopoverBarClass *klass)
-{
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
-  object_class->dispose = gtk_popover_bar_dispose;
-  object_class->set_property = gtk_popover_bar_set_property;
-  object_class->get_property = gtk_popover_bar_get_property;
-
-  widget_class->focus = gtk_popover_bar_focus;
-
-=======
-  object_class->dispose = gtk_popover_menu_bar_dispose;
-  object_class->set_property = gtk_popover_menu_bar_set_property;
-  object_class->get_property = gtk_popover_menu_bar_get_property;
-
-  widget_class->focus = gtk_popover_menu_bar_focus;
-
-  /**
-   * GtkPopoverMenuBar:menu-model:
-   *
-   * The #GMenuModel from which the menu bar is created.
-   *
-   * The model should only contain submenus as toplevel
-   * items.
-   */
->>>>>>> 2cfe644c96... fix up finalization:gtk/gtkpopovermenubar.c
-  bar_props[PROP_MENU_MODEL] =
-      g_param_spec_object ("menu-model",
-                           P_("Menu model"),
-                           P_("The model from which the bar is made."),
-                           G_TYPE_MENU_MODEL,
-                           GTK_PARAM_READWRITE);
-
-  g_object_class_install_properties (object_class, LAST_PROP, bar_props);
-
-  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
-  gtk_widget_class_set_css_name (widget_class, I_("menubar"));
-}
-
-static void
-gtk_popover_bar_init (GtkPopoverBar *bar)
-{
-}
-
-GtkWidget *
-gtk_popover_bar_new_from_model (GMenuModel *model)
-{
-  return g_object_new (GTK_TYPE_POPOVER_BAR,
-                       "menu-model", model,
-                       NULL);
-}
-
-void
-gtk_popover_bar_set_menu_model (GtkPopoverBar *bar,
-                                GMenuModel    *model)
-{
-  g_return_if_fail (GTK_IS_POPOVER_BAR (bar));
-  g_return_if_fail (G_IS_MENU_MODEL (model));
-
-  if (g_set_object (&bar->model, model))
-    {
-      GtkWidget *child;
-      GtkActionMuxer *muxer;
-
-      while ((child = gtk_widget_get_first_child (GTK_WIDGET (bar))))
-        gtk_widget_destroy (child);
-
-      g_clear_pointer (&bar->tracker, gtk_menu_tracker_free);
-
-      muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (bar), TRUE);
-      bar->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (muxer),
-                                           model,
-                                           FALSE,
-                                           TRUE,
-                                           FALSE,
-                                           NULL,
-                                           tracker_insert,
-                                           tracker_remove,
-                                           bar);
-
-      g_object_notify_by_pspec (G_OBJECT (bar), bar_props[PROP_MENU_MODEL]);
-    }
-}
-
-GMenuModel *
-gtk_popover_bar_get_menu_model (GtkPopoverBar *bar)
-{
-  g_return_val_if_fail (GTK_IS_POPOVER_BAR (bar), NULL);
-
-  return bar->model;
-}
diff --git a/gtk/gtkpopoverbar.h b/gtk/gtkpopoverbar.h
deleted file mode 100644 (file)
index eca22b5..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 2019 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __GTK_POPOVER_BAR_H__
-#define __GTK_POPOVER_BAR_H__
-
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtkpopover.h>
-
-
-G_BEGIN_DECLS
-
-
-#define        GTK_TYPE_POPOVER_BAR               (gtk_popover_bar_get_type ())
-#define GTK_POPOVER_BAR(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_BAR, GtkPopoverBar))
-#define GTK_IS_POPOVER_BAR(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_BAR))
-
-typedef struct _GtkPopoverBar GtkPopoverBar;
-
-GDK_AVAILABLE_IN_ALL
-GType        gtk_popover_bar_get_type       (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkWidget *  gtk_popover_bar_new_from_model (GMenuModel    *model);
-
-GDK_AVAILABLE_IN_ALL
-void         gtk_popover_bar_set_menu_model (GtkPopoverBar *bar,
-                                             GMenuModel    *model);
-GDK_AVAILABLE_IN_ALL
-GMenuModel * gtk_popover_bar_get_menu_model (GtkPopoverBar *bar);
-
-G_END_DECLS
-
-
-#endif /* __GTK_POPOVER_BAR_H__ */
diff --git a/gtk/gtkpopovermenubar.c b/gtk/gtkpopovermenubar.c
new file mode 100644 (file)
index 0000000..65bf0e5
--- /dev/null
@@ -0,0 +1,531 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * Authors:
+ * - Matthias Clasen <mclasen@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkpopovermenubar.h"
+#include "gtkpopovermenu.h"
+
+#include "gtkboxlayout.h"
+#include "gtklabel.h"
+#include "gtkmenubutton.h"
+#include "gtkintl.h"
+#include "gtkprivate.h"
+#include "gtkmarshalers.h"
+#include "gtkstylecontext.h"
+#include "gtkgestureclick.h"
+#include "gtkeventcontrollerkey.h"
+#include "gtkeventcontrollermotion.h"
+#include "gtkactionmuxerprivate.h"
+#include "gtkmenutracker.h"
+#include "gtkwidgetprivate.h"
+#include "gtkmain.h"
+#include "gtknative.h"
+
+#define GTK_TYPE_POPOVER_MENU_BAR_ITEM    (gtk_popover_menu_bar_item_get_type ())
+#define GTK_POPOVER_MENU_BAR_ITEM(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_MENU_BAR_ITEM, GtkPopoverMenuBarItem))
+#define GTK_IS_POPOVER_MENU_BAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_MENU_BAR_ITEM))
+
+GType gtk_popover_menu_bar_item_get_type (void) G_GNUC_CONST;
+
+typedef struct _GtkPopoverMenuBarItem GtkPopoverMenuBarItem;
+
+struct _GtkPopoverMenuBar
+{
+  GtkWidget parent;
+
+  GMenuModel *model;
+  GtkMenuTracker *tracker;
+
+  GtkPopoverMenuBarItem *active_item;
+};
+
+typedef struct _GtkPopoverMenuBarClass GtkPopoverMenuBarClass;
+struct _GtkPopoverMenuBarClass
+{
+  GtkWidgetClass parent_class;
+};
+
+struct _GtkPopoverMenuBarItem
+{
+  GtkWidget parent;
+
+  GtkWidget *label;
+  GtkPopover *popover;
+};
+
+typedef struct _GtkPopoverMenuBarItemClass GtkPopoverMenuBarItemClass;
+struct _GtkPopoverMenuBarItemClass
+{
+  GtkWidgetClass parent_class;
+
+  void (* activate) (GtkPopoverMenuBarItem *item);
+};
+
+G_DEFINE_TYPE (GtkPopoverMenuBarItem, gtk_popover_menu_bar_item, GTK_TYPE_WIDGET)
+
+static void
+set_active_item (GtkPopoverMenuBar     *bar,
+                 GtkPopoverMenuBarItem *item,
+                 gboolean               popup)
+{
+  gboolean changed;
+  gboolean was_popup;
+
+  changed = item != bar->active_item;
+
+  if (bar->active_item)
+    was_popup = gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover));
+  else
+    was_popup = FALSE;
+
+  if (was_popup && changed)
+    gtk_popover_popdown (bar->active_item->popover);
+
+  if (changed)
+    {
+      GtkStyleContext *context;
+
+      if (bar->active_item)
+        {
+          context = gtk_widget_get_style_context (GTK_WIDGET (bar->active_item));
+          gtk_style_context_remove_class (context, "active");
+        }
+
+      bar->active_item = item;
+
+      if (bar->active_item)
+        {
+          context = gtk_widget_get_style_context (GTK_WIDGET (bar->active_item));
+          gtk_style_context_add_class (context, "active");
+        }
+    }
+
+  if (bar->active_item)
+    {
+      if (popup || (was_popup && changed))
+        gtk_popover_popup (bar->active_item->popover);
+      else if (changed)
+        gtk_widget_grab_focus (GTK_WIDGET (bar->active_item));
+    }
+}
+
+static void
+clicked_cb (GtkGesture *gesture,
+            int         n,
+            double      x,
+            double      y,
+            gpointer    data)
+{
+  GtkWidget *target;
+  GtkPopoverMenuBar *bar;
+
+  target = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
+  bar = GTK_POPOVER_MENU_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU_BAR));
+
+  set_active_item (bar, GTK_POPOVER_MENU_BAR_ITEM (target), TRUE);
+}
+
+static void
+enter_cb (GtkEventController *controller,
+          double              x,
+          double              y,
+          GdkCrossingMode     mode,
+          GdkNotifyType       type,
+          gpointer            data)
+{
+  GtkWidget *target;
+  GtkPopoverMenuBar *bar;
+
+  target = gtk_event_controller_get_widget (controller);
+
+  bar = GTK_POPOVER_MENU_BAR (gtk_widget_get_ancestor (target, GTK_TYPE_POPOVER_MENU_BAR));
+
+  set_active_item (bar, GTK_POPOVER_MENU_BAR_ITEM (target), FALSE);
+}
+
+static gboolean
+gtk_popover_menu_bar_focus (GtkWidget        *widget,
+                            GtkDirectionType  direction)
+{
+  GtkPopoverMenuBar *bar = GTK_POPOVER_MENU_BAR (widget);
+  GtkWidget *next;
+  if (bar->active_item &&
+      gtk_widget_get_mapped (GTK_WIDGET (bar->active_item->popover)))
+    {
+      if (gtk_widget_child_focus (GTK_WIDGET (bar->active_item->popover), direction))
+        return TRUE;
+    }
+
+  if (direction == GTK_DIR_LEFT)
+    {
+      if (bar->active_item)
+        next = gtk_widget_get_prev_sibling (GTK_WIDGET (bar->active_item));
+      else
+        next = NULL;
+
+      if (next == NULL)
+        next = gtk_widget_get_last_child (GTK_WIDGET (bar));
+    }
+  else if (direction == GTK_DIR_RIGHT)
+    {
+      if (bar->active_item)
+        next = gtk_widget_get_next_sibling (GTK_WIDGET (bar->active_item));
+      else
+        next = NULL;
+
+      if (next == NULL)
+        next = gtk_widget_get_first_child (GTK_WIDGET (bar));
+    }
+  else
+    return FALSE;
+
+  set_active_item (bar, GTK_POPOVER_MENU_BAR_ITEM (next), FALSE);
+
+  return TRUE;
+}
+
+static void
+gtk_popover_menu_bar_item_init (GtkPopoverMenuBarItem *item)
+{
+  GtkEventController *controller;
+
+  gtk_widget_set_can_focus (GTK_WIDGET (item), TRUE);
+
+  item->label = g_object_new (GTK_TYPE_LABEL,
+                              "use-underline", TRUE,
+                              NULL);
+  gtk_widget_set_parent (item->label, GTK_WIDGET (item));
+
+  controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+  g_signal_connect (controller, "pressed", G_CALLBACK (clicked_cb), NULL);
+  gtk_widget_add_controller (GTK_WIDGET (item), controller);
+
+  controller = gtk_event_controller_motion_new ();
+  gtk_event_controller_set_propagation_limit (controller, GTK_LIMIT_NONE);
+  g_signal_connect (controller, "enter", G_CALLBACK (enter_cb), NULL);
+  gtk_widget_add_controller (GTK_WIDGET (item), controller);
+}
+
+static void
+gtk_popover_menu_bar_item_dispose (GObject *object)
+{
+  GtkPopoverMenuBarItem *item = GTK_POPOVER_MENU_BAR_ITEM (object);
+
+  g_clear_pointer (&item->label, gtk_widget_unparent);
+  g_clear_pointer ((GtkWidget **)&item->popover, gtk_widget_unparent);
+
+  G_OBJECT_CLASS (gtk_popover_menu_bar_item_parent_class)->dispose (object);
+}
+
+static void
+gtk_popover_menu_bar_item_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (gtk_popover_menu_bar_item_parent_class)->finalize (object);
+}
+
+static void
+gtk_popover_menu_bar_item_measure (GtkWidget      *widget,
+                                   GtkOrientation  orientation,
+                                   int             for_size,
+                                   int            *minimum,
+                                   int            *natural,
+                                   int            *minimum_baseline,
+                                   int            *natural_baseline)
+{
+  GtkPopoverMenuBarItem *item = GTK_POPOVER_MENU_BAR_ITEM (widget);
+
+  gtk_widget_measure (item->label, orientation, for_size,
+                      minimum, natural,
+                      minimum_baseline, natural_baseline);
+}
+
+static void
+gtk_popover_menu_bar_item_size_allocate (GtkWidget *widget,
+                                         int        width,
+                                         int        height,
+                                         int        baseline)
+{
+  GtkPopoverMenuBarItem *item = GTK_POPOVER_MENU_BAR_ITEM (widget);
+
+  gtk_widget_size_allocate (item->label,
+                            &(GtkAllocation) { 0, 0, width, height },
+                            baseline);
+
+  gtk_native_check_resize (GTK_NATIVE (item->popover));
+}
+
+static void
+gtk_popover_menu_bar_item_activate (GtkPopoverMenuBarItem *item)
+{
+  gtk_popover_popup (GTK_POPOVER (item->popover));
+}
+
+static void
+gtk_popover_menu_bar_item_class_init (GtkPopoverMenuBarItemClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = gtk_popover_menu_bar_item_dispose;
+  object_class->finalize = gtk_popover_menu_bar_item_finalize;
+
+  widget_class->measure = gtk_popover_menu_bar_item_measure;
+  widget_class->size_allocate = gtk_popover_menu_bar_item_size_allocate;
+
+  klass->activate = gtk_popover_menu_bar_item_activate;
+
+  widget_class->activate_signal =
+    g_signal_new (I_("activate"),
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_FIRST,
+                  G_STRUCT_OFFSET (GtkPopoverMenuBarItemClass, activate),
+                  NULL, NULL,
+                  NULL,
+                  G_TYPE_NONE, 0);
+
+  gtk_widget_class_set_css_name (widget_class, I_("item"));
+}
+enum
+{
+  PROP_0,
+  PROP_MENU_MODEL,
+  LAST_PROP
+};
+
+static GParamSpec * bar_props[LAST_PROP];
+
+G_DEFINE_TYPE (GtkPopoverMenuBar, gtk_popover_menu_bar, GTK_TYPE_WIDGET)
+
+static void
+tracker_remove (gint     position,
+                gpointer user_data)
+{
+  GtkWidget *bar = user_data;
+  GtkWidget *child;
+  int i;
+
+  for (child = gtk_widget_get_first_child (bar), i = 0;
+       child;
+       child = gtk_widget_get_next_sibling (child), i++)
+    {
+      if (i == position)
+        {
+          gtk_widget_destroy (child);
+          break;
+        }
+    }
+}
+
+static void
+popover_unmap (GtkPopover        *popover,
+               GtkPopoverMenuBar *bar)
+{
+  if (bar->active_item && bar->active_item->popover == popover)
+    set_active_item (bar, NULL, FALSE);
+}
+
+static void
+tracker_insert (GtkMenuTrackerItem *item,
+                gint                position,
+                gpointer            user_data)
+{
+  GtkPopoverMenuBar *bar = user_data;
+
+  if (gtk_menu_tracker_item_get_has_link (item, G_MENU_LINK_SUBMENU))
+    {
+      GtkPopoverMenuBarItem *widget;
+      GMenuModel *model;
+      GtkWidget *sibling;
+      GtkWidget *child;
+      GtkPopover *popover;
+      int i;
+
+      widget = g_object_new (GTK_TYPE_POPOVER_MENU_BAR_ITEM, NULL);
+      g_object_bind_property (item, "label",
+                              widget->label, "label",
+                              G_BINDING_SYNC_CREATE);
+
+      model = _gtk_menu_tracker_item_get_link (item, G_MENU_LINK_SUBMENU);
+      popover = GTK_POPOVER (gtk_popover_menu_new_from_model (GTK_WIDGET (widget), model));
+      gtk_popover_set_position (popover, GTK_POS_BOTTOM);
+      gtk_popover_set_has_arrow (popover, FALSE);
+      gtk_widget_set_halign (GTK_WIDGET (popover), GTK_ALIGN_START);
+
+      g_signal_connect (popover, "unmap", G_CALLBACK (popover_unmap), bar);
+
+      widget->popover = popover;
+
+      sibling = NULL;
+      for (child = gtk_widget_get_first_child (GTK_WIDGET (bar)), i = 1;
+           child;
+           child = gtk_widget_get_next_sibling (child), i++)
+        {
+          if (i == position)
+            {
+              sibling = child;
+              break;
+            }
+        }
+      gtk_widget_insert_after (GTK_WIDGET (widget), GTK_WIDGET (bar), sibling);
+    }
+  else
+    g_warning ("Don't know how to handle this item");
+}
+
+static void
+gtk_popover_menu_bar_set_property (GObject      *object,
+                                   guint         property_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  GtkPopoverMenuBar *bar = GTK_POPOVER_MENU_BAR (object);
+
+  switch (property_id)
+    {
+      case PROP_MENU_MODEL:
+        gtk_popover_menu_bar_set_menu_model (bar, g_value_get_object (value));
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+static void
+gtk_popover_menu_bar_get_property (GObject    *object,
+                                   guint       property_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  GtkPopoverMenuBar *bar = GTK_POPOVER_MENU_BAR (object);
+
+  switch (property_id)
+    {
+      case PROP_MENU_MODEL:
+        g_value_set_object (value, bar->model);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+    }
+}
+
+
+static void
+gtk_popover_menu_bar_dispose (GObject *object)
+{
+  GtkPopoverMenuBar *bar = GTK_POPOVER_MENU_BAR (object);
+  GtkWidget *child;
+
+  g_clear_pointer (&bar->tracker, gtk_menu_tracker_free);
+  g_clear_object (&bar->model);
+
+  while ((child = gtk_widget_get_first_child (GTK_WIDGET (bar))))
+    gtk_widget_destroy (child);
+
+  G_OBJECT_CLASS (gtk_popover_menu_bar_parent_class)->dispose (object);
+}
+
+static void
+gtk_popover_menu_bar_class_init (GtkPopoverMenuBarClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->dispose = gtk_popover_menu_bar_dispose;
+  object_class->set_property = gtk_popover_menu_bar_set_property;
+  object_class->get_property = gtk_popover_menu_bar_get_property;
+
+  widget_class->focus = gtk_popover_menu_bar_focus;
+
+  /**
+   * GtkPopoverMenuBar:menu-model:
+   *
+   * The #GMenuModel from which the menu bar is created.
+   *
+   * The model should only contain submenus as toplevel
+   * items.
+   */
+  bar_props[PROP_MENU_MODEL] =
+      g_param_spec_object ("menu-model",
+                           P_("Menu model"),
+                           P_("The model from which the bar is made."),
+                           G_TYPE_MENU_MODEL,
+                           GTK_PARAM_READWRITE);
+
+  g_object_class_install_properties (object_class, LAST_PROP, bar_props);
+
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
+  gtk_widget_class_set_css_name (widget_class, I_("menubar"));
+}
+
+static void
+gtk_popover_menu_bar_init (GtkPopoverMenuBar *bar)
+{
+}
+
+GtkWidget *
+gtk_popover_menu_bar_new_from_model (GMenuModel *model)
+{
+  return g_object_new (GTK_TYPE_POPOVER_MENU_BAR,
+                       "menu-model", model,
+                       NULL);
+}
+
+void
+gtk_popover_menu_bar_set_menu_model (GtkPopoverMenuBar *bar,
+                                     GMenuModel        *model)
+{
+  g_return_if_fail (GTK_IS_POPOVER_MENU_BAR (bar));
+  g_return_if_fail (G_IS_MENU_MODEL (model));
+
+  if (g_set_object (&bar->model, model))
+    {
+      GtkWidget *child;
+      GtkActionMuxer *muxer;
+
+      while ((child = gtk_widget_get_first_child (GTK_WIDGET (bar))))
+        gtk_widget_destroy (child);
+
+      g_clear_pointer (&bar->tracker, gtk_menu_tracker_free);
+
+      muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (bar), TRUE);
+      bar->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (muxer),
+                                           model,
+                                           FALSE,
+                                           TRUE,
+                                           FALSE,
+                                           NULL,
+                                           tracker_insert,
+                                           tracker_remove,
+                                           bar);
+
+      g_object_notify_by_pspec (G_OBJECT (bar), bar_props[PROP_MENU_MODEL]);
+    }
+}
+
+GMenuModel *
+gtk_popover_menu_bar_get_menu_model (GtkPopoverMenuBar *bar)
+{
+  g_return_val_if_fail (GTK_IS_POPOVER_MENU_BAR (bar), NULL);
+
+  return bar->model;
+}
diff --git a/gtk/gtkpopovermenubar.h b/gtk/gtkpopovermenubar.h
new file mode 100644 (file)
index 0000000..7fa1253
--- /dev/null
@@ -0,0 +1,53 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2019 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_POPOVER_MENU_BAR_H__
+#define __GTK_POPOVER_MENU_BAR_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkpopover.h>
+
+
+G_BEGIN_DECLS
+
+
+#define        GTK_TYPE_POPOVER_MENU_BAR               (gtk_popover_menu_bar_get_type ())
+#define GTK_POPOVER_MENU_BAR(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_MENU_BAR, GtkPopoverMenuBar))
+#define GTK_IS_POPOVER_MENU_BAR(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_MENU_BAR))
+
+typedef struct _GtkPopoverMenuBar GtkPopoverMenuBar;
+
+GDK_AVAILABLE_IN_ALL
+GType        gtk_popover_menu_bar_get_type       (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_ALL
+GtkWidget *  gtk_popover_menu_bar_new_from_model (GMenuModel        *model);
+
+GDK_AVAILABLE_IN_ALL
+void         gtk_popover_menu_bar_set_menu_model (GtkPopoverMenuBar *bar,
+                                                  GMenuModel        *model);
+GDK_AVAILABLE_IN_ALL
+GMenuModel * gtk_popover_menu_bar_get_menu_model (GtkPopoverMenuBar *bar);
+
+G_END_DECLS
+
+
+#endif /* __GTK_POPOVER_MENU_BAR_H__ */
index 2c844edbef607d51c79801fe56d1352a1bc3f129..98f80c4f04d5984a55be541f05d72bdcd99da10d 100644 (file)
@@ -296,8 +296,8 @@ gtk_public_sources = files([
   'gtkpasswordentry.c',
   'gtkpicture.c',
   'gtkpopover.c',
-  'gtkpopoverbar.c',
   'gtkpopovermenu.c',
+  'gtkpopovermenubar.c',
   'gtkprintcontext.c',
   'gtkprintoperation.c',
   'gtkprintoperationpreview.c',